package com.thememaker.util;

import com.thememake.entity.ThemeFileInfo;
import com.thememake.ui.dialog.AlertDialog;
import com.thememake.util.xml.fontcolor.ReadXmlUtils;
import com.thememaker.lockstyle.LockstylePaserUtils;
import com.thememaker.lockstyle.bean.Lockscreen;
import com.thememaker.lockstyle.bean.ui.BaseView;
import com.thememaker.lockstyle.bean.ui.Button;
import com.thememaker.lockstyle.bean.ui.Group;
import com.thememaker.lockstyle.bean.ui.Image;
import com.thememaker.lockstyle.parsii.ExpressionUtils;
import com.thememaker.lockstyle.parsii.LockscreenViewPaesiiUtils;
import javafx.application.Platform;
import org.w3c.dom.Document;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.Optional;

/**
 * @author yiyi.zheng 2018/9/26
 */
public class OPPOFaceRecognitionUtils {
    private static OPPOFaceRecognitionUtils oppoFaceRecognitionUtils;
    private ThemeFileInfo themeFileInfo;
    private Path lockscreenPath;
    private double screen_width = 1080;

    private LinkedHashMap<String, BaseView> editMap2160 = new LinkedHashMap<>();
    private LinkedHashMap<String, BaseView> editMap2280 = new LinkedHashMap<>();
    private LinkedHashMap<String, BaseView> editMap2340 = new LinkedHashMap<>();

    private Document document2160;
    private Lockscreen lockscreen2160;
    private LinkedHashMap<String, BaseView> map2160;
    private String xmlPath2160;
    private Document document2280;
    private Lockscreen lockscreen2280;
    private LinkedHashMap<String, BaseView> map2280;
    private String xmlPath2280;
    private Document document2340;
    private Lockscreen lockscreen2340;
    private LinkedHashMap<String, BaseView> map2340;
    private String xmlPath2340;

    public static OPPOFaceRecognitionUtils getInstance() {
        if (oppoFaceRecognitionUtils == null) {
            oppoFaceRecognitionUtils = new OPPOFaceRecognitionUtils();
        }

        return oppoFaceRecognitionUtils;
    }

    public void judgeFaceRecognition(ThemeFileInfo themeFileInfo, String oppoPath) {
        this.themeFileInfo = themeFileInfo;
        lockscreenPath = Paths.get(themeFileInfo.getThemeDir().getPath(), themeFileInfo.getThemeType(), ThemeFileInfo.LOCKSTYLE_NAME, "lockscreen");
        createLockObject(Paths.get(oppoPath, "2x1", "manifest.xml").toString(), 2160);
        createLockObject(Paths.get(oppoPath, "19x9", "manifest.xml").toString(), 2280);
        createLockObject(Paths.get(oppoPath, "13x6", "manifest.xml").toString(), 2340);
        judgeFaceRecognition();
    }

    private void createLockObject(String xmlPath, double screen_height) {
        if (screen_height == 2160) {
            this.xmlPath2160 = xmlPath;
            ExpressionUtils expressionUtils2160 = ExpressionUtils.getInstance(screen_width, screen_height);
            document2160 = ReadXmlUtils.loadXml(xmlPath);
            lockscreen2160 = LockstylePaserUtils.paserLockScreenXml(document2160);
            map2160 = lockscreen2160.getLockScreenViewMap();
            classifyBaseView(map2160, expressionUtils2160, screen_height);
            editViewLocation(editMap2160, expressionUtils2160);
        } else if (screen_height == 2280) {
            this.xmlPath2280 = xmlPath;
            ExpressionUtils expressionUtils2280 = ExpressionUtils.getInstance(screen_width, screen_height);
            document2280 = ReadXmlUtils.loadXml(xmlPath);
            lockscreen2280 = LockstylePaserUtils.paserLockScreenXml(document2280);
            map2280 = lockscreen2280.getLockScreenViewMap();
            classifyBaseView(map2280, expressionUtils2280, screen_height);
            editViewLocation(editMap2280, expressionUtils2280);
        } else if (screen_height == 2340) {
            this.xmlPath2340 = xmlPath;
            ExpressionUtils expressionUtils2340 = ExpressionUtils.getInstance(screen_width, screen_height);
            document2340 = ReadXmlUtils.loadXml(xmlPath);
            lockscreen2340 = LockstylePaserUtils.paserLockScreenXml(document2340);
            map2340 = lockscreen2340.getLockScreenViewMap();
            classifyBaseView(map2340, expressionUtils2340, screen_height);
            editViewLocation(editMap2340, expressionUtils2340);
        }
    }

    private void judgeFaceRecognition() {
        if (!editMap2160.isEmpty() || !editMap2280.isEmpty() || !editMap2340.isEmpty()) {
            Platform.runLater(() -> {
//                new AlertDialog.Builder(null, "转换提示")
//                        .setMessage("检测到OPPO人脸识别位置上有其他组件，是否移动这些组件？")
//                        .setCancelButton("不，找佳俊")
//                        .setOkButton("好的", true, o -> {
//                            save(editMap2160, map2160, document2160, lockscreen2160, xmlPath2160);
//                            save(editMap2280, map2280, document2280, lockscreen2280, xmlPath2280);
//                            save(editMap2340, map2340, document2340, lockscreen2340, xmlPath2340);
//                        })
//                        .build().show();
                new AlertDialog.Builder(null, "转换提示")
                        .setMessage("检测到OPPO人脸识别位置上有其他组件，请联系锁屏制作人员进行修改。")
                        .setOkButton("好的", true)
                        .build().show();
            });
        }
    }

    private void classifyBaseView(LinkedHashMap<String, BaseView> map, ExpressionUtils expressionUtils, double screen_height) {
        map.keySet().forEach(key -> {
            BaseView baseView = map.get(key);
            if (baseView instanceof Group) {
                Group group = (Group) baseView;
                classifyBaseView(group.getGroupViewMap(), expressionUtils, screen_height);
            } else if (baseView instanceof Image) {
                Image image = (Image) baseView;
                Path path = LockscreenViewPaesiiUtils.getInstance(expressionUtils).paesiiImagePath(image, lockscreenPath.toString());
                javafx.scene.image.Image imageFX = new javafx.scene.image.Image("file:" + path.toString());
                double x = expressionUtils.parseExpr(Optional.ofNullable(image.getX()).orElse("0"));
                double y = expressionUtils.parseExpr(Optional.ofNullable(image.getY()).orElse("0"));
                image.setW(String.valueOf((int) imageFX.getWidth()));
                image.setH(String.valueOf((int) imageFX.getHeight()));
                boolean addMap = judgeViewLocation(x, y, imageFX.getWidth(), imageFX.getHeight(), screen_height);
                if (addMap) {
                    if (screen_height == 2160) {
                        editMap2160.put(image.getId(), image);
                    } else if (screen_height == 2280) {
                        editMap2280.put(image.getId(), image);
                    } else if (screen_height == 2340) {
                        editMap2340.put(image.getId(), image);
                    }
                }
            } else if (baseView instanceof Button) {
                Button button = (Button) baseView;
                double x = expressionUtils.parseExpr(Optional.ofNullable(button.getX()).orElse("0"));
                double y = expressionUtils.parseExpr(Optional.ofNullable(button.getY()).orElse("0"));
                double w = expressionUtils.parseExpr(Optional.ofNullable(button.getW()).orElse("0"));
                double h = expressionUtils.parseExpr(Optional.ofNullable(button.getH()).orElse("0"));
                if (judgeViewLocation(x, y, w, h, screen_height)) {
                    if (screen_height == 2160) {
                        editMap2160.put(button.getId(), button);
                    } else if (screen_height == 2280) {
                        editMap2280.put(button.getId(), button);
                    } else if (screen_height == 2340) {
                        editMap2340.put(button.getId(), button);
                    }
                }
            }
        });
    }

    private int fixY;

    // 2160 390 1618 300 282
    // 2280 390 1680 300 282
    // 2340 390 1812 300 282
    private boolean judgeViewLocation(double x, double y, double w, double h, double screen_height) {
        fixY = 0;
        if (screen_height == 2160) {
            fixY = 1618;
        } else if (screen_height == 2280) {
            fixY = 1680;
        } else if (screen_height == 2340) {
            fixY = 1812;
        }
        if (x + w > 390 && x < 390 + 300 && y + h > fixY && y < fixY + 282) {
            return true;
        } else {
            return false;
        }
    }

    private void editViewLocation(LinkedHashMap<String, BaseView> editMap, ExpressionUtils expressionUtils) {
        editMap.keySet().forEach(key -> {
            BaseView baseView = editMap.get(key);
            double x = expressionUtils.parseExpr(Optional.ofNullable(baseView.getX()).orElse("0"));
            double y = expressionUtils.parseExpr(Optional.ofNullable(baseView.getY()).orElse("0"));
            double w = expressionUtils.parseExpr(Optional.ofNullable(baseView.getW()).orElse("0"));
            double h = expressionUtils.parseExpr(Optional.ofNullable(baseView.getH()).orElse("0"));
            if (x < 390 + 300 / 2) {
                int newX = (int) (x + w - 300);
                baseView.setX(baseView.getX() + "-" + newX);
            } else {
                int newX = (int) (390 + 300 - x);
                baseView.setX(baseView.getX() + "+" + newX);
            }
            if (y < fixY + 282 / 2) {
                int newY = (int) (y + h - fixY);
                baseView.setY(baseView.getY() + "-" + newY);
            } else {
                int newY = (int) (fixY + 282 - y);
                baseView.setY(baseView.getY() + "+" + newY);
            }
        });
    }

    private void save(LinkedHashMap<String, BaseView> editMap, LinkedHashMap<String, BaseView> map, Document document, Lockscreen lockscreen, String xmlPath) {
        editMap.keySet().forEach(key -> {
            map.put(key, editMap.get(key));
        });
        lockscreen.setLockScreenViewMap(map);
        LockstylePaserUtils.saveLockScreenXml(themeFileInfo, document, lockscreen, Paths.get(xmlPath).toFile());
    }
}
